﻿using System;
using System.Collections.Generic;
using System.ServiceModel;
using Microsoft.Practices.Unity;
using JTLeigh.Commerce.Spencer.Core.Common;
using JTLeigh.Commerce.Spencer.Features.ProductImages.Business.Services;
using JTLeigh.Commerce.Spencer.Features.ProductImages.Service.Contracts.Runtime.Common;

// aliases for entities
using LocalizedProductImageE = JTLeigh.Commerce.Spencer.Features.ProductImages.Common.Entities.LocalizedProductImage;
using LocalizedProductImageViewE = JTLeigh.Commerce.Spencer.Features.ProductImages.Common.Entities.LocalizedProductImageView;
using LocalizedProductImageSizeE = JTLeigh.Commerce.Spencer.Features.ProductImages.Common.Entities.LocalizedProductImageSize;
using ProductImageVariantE = JTLeigh.Commerce.Spencer.Features.ProductImages.Common.Entities.ProductImageVariant;

// aliases for contracts
using GetProductImageSummariesRequestC = JTLeigh.Commerce.Spencer.Features.ProductImages.Service.Contracts.Runtime.GetProductImageSummaries.GetProductImageSummariesRequest;
using GetProductImageSummariesResponseC = JTLeigh.Commerce.Spencer.Features.ProductImages.Service.Contracts.Runtime.GetProductImageSummaries.GetProductImageSummariesResponse;
using ProductImageSizeC = JTLeigh.Commerce.Spencer.Features.ProductImages.Service.Contracts.Runtime.GetProductImageSummaries.ProductImageSize;
using ProductImageSummaryC = JTLeigh.Commerce.Spencer.Features.ProductImages.Service.Contracts.Runtime.GetProductImageSummaries.ProductImageSummary;
using JTLeigh.Commerce.Spencer.Core.Service.Contracts;

namespace JTLeigh.Commerce.Spencer.Features.ProductImages.Service.Commands.Runtime
{

	/// <summary>
	/// Command for getting a single image per product for multiple products for a single view and 
	/// size combination.
	/// </summary>
	public class GetProductImageSummariesCommand
	{

		#region Properties

		/// <summary>
		/// Gets or sets the product image metadata service to use to get product image metadata.
		/// </summary>
		/// <value>An <see cref="IProductImageMetadataService"/> implementation.</value>
		[Dependency]
		public IProductImageMetadataService ProductImageMetadataService { get; set; }

		/// <summary>
		/// Gets or sets the product image service to use to get product images.
		/// </summary>
		/// <value>An <see cref="IProductImageService"/> implementation.</value>
		[Dependency]
		public IProductImageService ProductImageService { get; set; }

		#endregion // Properties

		#region Methods

		/// <summary>
		/// Gets a single image per product for multiple products for a single view and size 
		/// combination.
		/// </summary>
		/// <param name="request">The <see cref="GetProductImageSummariesRequestC"/> request object.</param>
		/// <returns>The <see cref="GetProductImageSummariesResponseC"/> response object.</returns>
		public GetProductImageSummariesResponseC GetProductImageSummaries(GetProductImageSummariesRequestC request)
		{
			LocalizedProductImageSizeE size;
			LocalizedProductImageViewE view;
			Dictionary<Guid, LocalizedProductImageE> images;
			ProductImageVariantE variant;
			GetProductImageSummariesResponseC response;
			ProductImageSummaryC summary;

			Safety.AssertArgumentNotNull("request", request);

			size = ProductImageMetadataService.GetProductImageSizeByWellKnownSizeCode(request.TenantId, request.WellKnownSizeCode, request.CultureId);
			if (size == null)
			{
				// TODO: Log this condition.
				throw new FaultException<UnknownProductImageSizeFault>(new UnknownProductImageSizeFault
				{
					TenantId = request.TenantId,
					WellKnownSizeCode = request.WellKnownSizeCode
				}
				);
			}

			view = ProductImageMetadataService.GetProductImageViewByWellKnownViewCode(request.TenantId, request.WellKnownViewCode, request.CultureId);
			if (view == null)
			{
				// TODO: Log this condition.
				throw new FaultException<UnknownProductImageViewFault>(new UnknownProductImageViewFault
				{
					TenantId = request.TenantId,
					WellKnownViewCode = request.WellKnownViewCode
				}
				);
			}

			response = new GetProductImageSummariesResponseC();

			response.Size = new ProductImageSizeC
			{
				Width = size.Width,
				Height = size.Height
			};

			response.Summaries = new Dictionary<FullyQualifiedProductId, ProductImageSummaryC>();

			foreach (FullyQualifiedProductId productId in request.ProductIds)
			{

				images = ProductImageService.GetProductImages(request.TenantId, productId.CatalogId, productId.ProductId, request.CultureId);

				summary = null;

				// NOTE: images is keyed on ImageId, not ViewId, so we need to loop through all images
				// until we find one with the correct ViewId.
				foreach (LocalizedProductImageE image in images.Values)
				{
					if (image.ViewId.Equals(view.ViewId))
					{
						// NOTE: variants is keyed on SizeId, so we don't need to loop through all 
						// variants, and can just try to get the one we need instead.
						if (image.Variants.TryGetValue(size.SizeId, out variant))
						{
							summary = new ProductImageSummaryC
							{
								AlternativeText = image.AlternativeText,
								UsagePermissionText = image.UsagePermissionText,
								Path = variant.Path
							};
							break;
						}
					}
				}

				if (summary == null)
				{
					summary = new ProductImageSummaryC
					{
						AlternativeText = null, // FEAT: Return default alternative text for this tenant?
						UsagePermissionText = null, // FEAT: Return default usage permission text for this tenant?
						Path = size.MissingImagePath
					};
				}

				response.Summaries.Add(productId, summary);

			}

			return response;
		}

		#endregion // Methods

	}

}
